//
//  SourceTextView.m
//  iCodeMac
//
//  Created by Andrew Barry on 31/03/09.
//  Copyright 2009 Barry Computer Services. All rights reserved.
//

#import "SourceTextView.h"
#import "MyTextViewDelegate.h"
#import "JavascriptProject.h"

static NSArray *gKeywords, *gGraphicsComplete;

@implementation SourceTextView

#define EDITORFONT @"Bitstream Vera Sans Mono"
#define EDITORFONT2 @"Monaco"

-(void)awakeFromNib {
	NSFont *stdFont = [[NSFontManager sharedFontManager] fontWithFamily: EDITORFONT traits: 0 weight: 5 size: 12];
	if (!stdFont)
		stdFont = [[NSFontManager sharedFontManager] fontWithFamily: EDITORFONT2 traits: 0 weight: 5 size: 12];
	
	if (stdFont)
		[self setFont: stdFont];
	if (document) {
		MyTextViewDelegate *delegate = [self delegate];

		JavascriptProject *project = [JavascriptProject projectForDocument:document];
		if (project) {
			NSString *name;
			if (documentName != nil)
				name = documentName;
			else
				name = [document documentFile];
			
			NSArray *arr = [project breakpointsForWindow: name];
			if (arr && [arr count] > 0) {
				for (int idx = 0; idx < [arr count]; idx++)
					[[delegate breakpoints] addObject:[arr objectAtIndex:idx]];
				[delegate codeLoaded];
			}
		}
	}
}

-(void)setDocumentName:(NSString *) name {
	[documentName autorelease];
	documentName = [name retain];
}

-(BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem {
	SEL theAction = [anItem action];
	
	if (theAction == @selector(debugBreakpoint:)) {
		JavascriptProject *project = nil;
		if (document)
			project = [JavascriptProject projectForDocument:document];
		return project != nil;
	}
	return [super validateUserInterfaceItem:anItem];
}

-(void)debugBreakpoint:(id) sender {
	MyTextViewDelegate *delegate = [self delegate];
	[delegate toggleBreakpoint];
}

-(void)saveBreakpoints {
	MyTextViewDelegate *delegate = [self delegate];
	if (document) {
		JavascriptProject *project = [JavascriptProject projectForDocument:document];
		if (project) {
			NSString *name;
			if (documentName != nil)
				name = documentName;
			else
				name = [document documentFile];
			[project saveBreakpoints: [delegate breakpoints] forWindow: name];
		}
	}
}

-(void)reloadBreakpoints {
	if (document) {
		MyTextViewDelegate *delegate = [self delegate];
		
		JavascriptProject *project = [JavascriptProject projectForDocument:document];
		if (project) {
			NSString *name;
			if (documentName != nil)
				name = documentName;
			else
				name = [document documentFile];
			
			[[delegate breakpoints] removeAllObjects];
			NSArray *arr = [project breakpointsForWindow: name];
			if (arr && [arr count] > 0) {
				for (int idx = 0; idx < [arr count]; idx++)
					[[delegate breakpoints] addObject:[arr objectAtIndex:idx]];
			}
			[delegate codeLoaded];
		}
	}
}

-(void)setRunMarker: (int) lineno {
	MyTextViewDelegate *delegate = [self delegate];
	[delegate setRunMarker: lineno];
}

-(NSString *)grabPreviousIdentifier: (NSString *) text forPos:(int *) pos {
	int p = *pos;
	NSMutableString *priorIdent = [[NSMutableString new] autorelease];
	while (p > 0) {
		unichar ch = [text characterAtIndex:p-1];
		if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9') {
			[priorIdent insertString:[NSString stringWithCharacters:&ch length:1]  atIndex:0];
			p--;
		} else
			break;
	}
	*pos = p;
	return priorIdent;
}

-(NSArray *)completionsForPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index {
	NSString *text = [self string];
	NSString *range = [text substringWithRange:charRange];
	
	NSMutableArray *options = [[NSMutableArray new] autorelease];
	
	// is it a dotted item?
	if (charRange.location > 0 && [text characterAtIndex:charRange.location - 1] == '.') {
		int p = charRange.location - 1;
		
		NSString *priorIdent = [self grabPreviousIdentifier: text forPos:&p];
		NSArray *objectMembers = nil;

		if ([priorIdent isEqualToString:@"this"]) {
			// we have a winner
			if ([document respondsToSelector: @selector(autocompletesForThis)]){
				objectMembers = [document autocompletesForThis];
			}
		} else if ([priorIdent isEqualToString:@"HTTP"]) {
			objectMembers = [NSArray arrayWithObjects:@"get(", @"post(", nil];
		} else if ([priorIdent isEqualToString:@"SQL"]) {
			objectMembers = [NSArray arrayWithObjects:@"connect(", @"close(", @"execute(", @"select(", nil];
		} else if ([priorIdent isEqualToString:@"Curl"]) {
			objectMembers = [NSArray arrayWithObjects:@"upload(", nil];
		} else if ([priorIdent isEqualToString:@"Keychain"]) {
			objectMembers = [NSArray arrayWithObjects:@"loadInternetPassword(", @"storeInternetPassword(", nil];
		} else if ([priorIdent isEqualToString:@"Graphics"]) {
			if (!gGraphicsComplete) {
				NSString *gKeywordsPath = [[NSBundle mainBundle] pathForResource:@"graphicsAutocomplete" ofType:@"txt"];
				NSString *gKeywordsStr = [NSString stringWithContentsOfFile:gKeywordsPath];
				gGraphicsComplete = [[gKeywordsStr componentsSeparatedByString: @"\n"] retain];
			}
			objectMembers = gGraphicsComplete;
		} else if ([priorIdent isEqualToString:@"File"]) {
			objectMembers = [NSArray arrayWithObjects:@"read(", @"write(", @"append(", @"deleteFile(", @"move(", @"copy(", @"exists(", @"readImage(", nil];
		} else if ([priorIdent isEqualToString:@"Dir"]) {
			objectMembers = [NSArray arrayWithObjects:@"current", @"create(", @"names(", @"list(", @"applicationSupport", @"downloads", @"applications", @"developer", @"library", @"users", @"documents", @"desktop", @"home", nil];
		} else {
			if (p > 0 && [text characterAtIndex:p - 1] == '.') {
				p--;
				NSString *priorPriorIdent = [self grabPreviousIdentifier: text forPos:&p];
				if ([priorPriorIdent isEqualToString:@"this"]) {
					if ([document respondsToSelector: @selector(autocompletesForMember:)]){
						objectMembers = [document autocompletesForMember: priorIdent];
					}
				}
			}
		}

		if (objectMembers) {
			for (int idx = 0; idx < [objectMembers count]; idx++) {
				NSString *item = [objectMembers objectAtIndex:idx];
				if ([item length] > 0 && charRange.length < [item length] && [range isEqualToString:[item substringToIndex:charRange.length]])
					[options addObject:item];
			}
		}
	} else {
		if (charRange.length == 0)
			return nil;

		if (!gKeywords) {
			NSString *gKeywordsPath = [[NSBundle mainBundle] pathForResource:@"autocomplete" ofType:@"txt"];
			NSString *gKeywordsStr = [NSString stringWithContentsOfFile:gKeywordsPath];
			gKeywords = [[gKeywordsStr componentsSeparatedByString: @"\n"] retain];
		}
		
		for (int idx = 0; idx < [gKeywords count]; idx++) {
			NSString *item = [gKeywords objectAtIndex:idx];
			if ([item length] > 0)
				if (charRange.length < [item length] && [range isEqualToString:[item substringToIndex:charRange.length]])
					[options addObject:item];
		}
	}
	
	if ([options count] == 1)
		*index = 0;
	else
		*index = -1;
	[options sortUsingSelector:@selector(caseInsensitiveCompare:)];
	return options;
}

- (NSRange)rangeForUserCompletion {
	NSRange cursel = [self selectedRange];
	if (cursel.length == 0) {
		NSString *text = [self string];
		int p = cursel.location;
		if (p > 0 && [text characterAtIndex:p - 1] == '.') {
			return NSMakeRange(p, 0);
		}
	}
	return [super rangeForUserCompletion];
}


- (void)keyDown:(NSEvent *)theEvent {
	if (([theEvent modifierFlags] & NSControlKeyMask && [theEvent keyCode] == 49) || ([theEvent keyCode] == 53)) {
		[self complete: self];
		return;
	}
	[super keyDown:theEvent];
}



@end
